package com.seckill.service.impl;

import com.seckill.common.service.RedisService;
import com.seckill.dao.PromoDOMapper;
import com.seckill.domain.PromoDO;
import com.seckill.model.dto.ItemDTO;
import com.seckill.model.dto.PromoDTO;
import com.seckill.model.dto.UserDTO;
import com.seckill.service.ItemService;
import com.seckill.service.PromoService;
import com.seckill.service.UserService;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author lill
 * @date 2019-06-24
 */
@Service
public class PromoServiceImpl implements PromoService {

    @Autowired
    private PromoDOMapper promoDOMapper;

    @Autowired
    private ItemService itemService;

    @Autowired
    private RedisService<Integer> integerRedisService;

    @Autowired
    private RedisService<String> stringRedisService;

    @Autowired
    private UserService userService;

    @Override
    public PromoDTO getPromoByItemId(Integer itemId) {
        //获取对应商品的秒杀信息
        PromoDO promoDO = promoDOMapper.selectByItemId(itemId);
        PromoDTO promoDTO = convertFromDataObject(promoDO);
        if (null == promoDTO) {
            return null;
        }

        //判断秒杀活动的当前状态
        if (promoDTO.getStartDate().isAfterNow()) {
            promoDTO.setStatus(1);
        } else if (promoDTO.getEndDate().isBeforeNow()) {
            promoDTO.setStatus(3);
        } else {
            promoDTO.setStatus(2);
        }

        return promoDTO;
    }

    private PromoDTO convertFromDataObject(PromoDO promoDO) {
        if (null == promoDO) {
            return null;
        }
        PromoDTO promoModel = new PromoDTO();
        BeanUtils.copyProperties(promoDO, promoModel);
        promoModel.setStartDate(new DateTime(promoDO.getStartDate()));
        promoModel.setEndDate(new DateTime(promoDO.getEndDate()));

        return promoModel;
    }

    @Override
    public void publishPromo(Integer promoId) {
        //通过活动id获取活动
        PromoDO promoDO = promoDOMapper.selectByPrimaryKey(promoId);
        if (null == promoDO.getItemId() || promoDO.getItemId().intValue() == 0) {
            return;
        }
        ItemDTO itemDTO = itemService.getItemById(promoDO.getItemId());

        //将库存同步到redis内
        integerRedisService.setCache("promo_item_stock_" + itemDTO.getId(), itemDTO.getStock());

        // 设置大闸数量
        integerRedisService.setCache("promo_door_count_" + itemDTO.getId(), itemDTO.getStock() * 5);
    }

    @Override
    public String generateSecondKillToken(Integer promoId, Integer itemId, Integer userId) {
        // 判断是否库存已售罄，若对应的售罄key存在，则直接返回下单失败
        if (stringRedisService.exists("promo_item_stock_invalid_" + itemId)) {
            return null;
        }
        PromoDO promoDO = promoDOMapper.selectByPrimaryKey(promoId);
        if (null == promoDO) {
            return null;
        }
        PromoDTO promoDTO = convertFromDataObject(promoDO);

        // 判断当前时间是否秒杀活动即将开始或正在进行
        if (promoDTO.getStartDate().isAfterNow()) {
            promoDTO.setStatus(1);
        } else if (promoDTO.getEndDate().isBeforeNow()) {
            promoDTO.setStatus(3);
        } else {
            promoDTO.setStatus(2);
        }
        // 判断活动是否正在进行
        if (promoDTO.getStatus().intValue() != 2) {
            return null;
        }
        // 判断item信息是否存在
        ItemDTO itemDTO = itemService.getItemByIdInCache(itemId);
        if (null == itemDTO) {
            return null;
        }
        // 判断用户信息是否存在
        UserDTO userModel = userService.getUserByIdInCache(userId);
        if (userModel == null) {
            return null;
        }

        // 获取秒杀大闸的count数量
        long result = integerRedisService.increment("promo_door_count_" + promoId, -1);
        if (result < 0) {
            return null;
        }
        // 生成token并且存入redis内并给一个5分钟的有效期
        String token = UUID.randomUUID().toString().replace("-", "");

        stringRedisService.setCache("promo_token_" + promoId + "_userid_" + userId + "_itemid_" + itemId, token, 5, TimeUnit.MINUTES);
        return token;
    }
}
